package org.codefinger.dao.util.jdbc;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Date;

public class JDBCUtil {

	public static void freeResource(Connection connection, Statement statement, ResultSet resultSet) {
		if (resultSet != null) {
			try {
				resultSet.close();
			} catch (SQLException e) {
			}
		}
		if (statement != null) {
			try {
				statement.close();
			} catch (SQLException e) {
			}
		}
		if (connection != null) {
			try {
				connection.close();
			} catch (SQLException e) {
			}
		}
	}

	public static void setStatementParams(PreparedStatement statement, Object[] params) throws SQLException {
		int index = 1;
		for (Object value : params) {
			if (value == null) {
				statement.setString(index++, null);
				continue;
			}
			getSetter(value.getClass()).setParam(statement, index++, value);
		}
	}

	public static void setStatementParam(PreparedStatement statement, Object param, int index) throws SQLException {
		if(param == null){
			statement.setString(index, null);
			return;
		}
		getSetter(param.getClass()).setParam(statement, index++, param);
	}

	public static StatementSetter getSetter(Class<?> clas) {
		if (clas == Integer.class) {
			return IntSetter.INSTANCE;
		}
		if (clas == String.class) {
			return StringSetter.INSTANCE;
		}
		if (clas == Long.class) {
			return LongSetter.INSTANCE;
		}
		if (Date.class.isAssignableFrom(clas)) {
			return DateSetter.INSTANCE;
		}
		if (clas == Boolean.class) {
			return BooleanSetter.INSTANCE;
		}
		if (clas == Double.class) {
			return DoubleSetter.INSTANCE;
		}
		if (clas == BigDecimal.class) {
			return BigDecimalSetter.INSTANCE;
		}
		if (clas == Float.class) {
			return FloatSetter.INSTANCE;
		}
		if (clas == BigInteger.class) {
			return BigIntegerSetter.INSTANCE;
		}
		if (clas == Byte.class) {
			return ByteSetter.INSTANCE;
		}
		if (clas == Short.class) {
			return ShortSetter.INSTANCE;
		}
		return StringSetter.INSTANCE;
	}

	public static Object getResult(ResultSet resultSet, int index, Class<?> type) throws SQLException {
		return getRSGetter(type).getResult(resultSet, index);
	}
	
	public static ResultSetGetter getRSGetter(Class<?> clas) {
		if (clas == int.class || clas == Integer.class) {
			return IntRSGetter.INSTANCE;
		}
		if (clas == String.class) {
			return StringRSGetter.INSTANCE;
		}
		if (clas == long.class || clas == Long.class) {
			return LongRSGetter.INSTANCE;
		}
		if (clas == Date.class) {
			return DateRSGetter.INSTANCE;
		}
		if (clas == boolean.class || clas == Boolean.class) {
			return BooleanRSGetter.INSTANCE;
		}
		if (clas == double.class || clas == Double.class) {
			return DoubleRSGetter.INSTANCE;
		}
		if (clas == BigDecimal.class) {
			return BigDecimalRSGetter.INSTANCE;
		}
		if (clas == float.class || clas == Float.class) {
			return FloatRSGetter.INSTANCE;
		}
		if (clas == BigInteger.class) {
			return BigIntegerRSGetter.INSTANCE;
		}
		if (clas == byte.class || clas == Byte.class) {
			return ByteRSGetter.INSTANCE;
		}
		if (clas == short.class || clas == Short.class) {
			return ShortRSGetter.INSTANCE;
		}
		return NullRSGetter.INSTANCE;
	}

	public static Object getResult(ResultSet resultSet, int index, int type) throws SQLException {
		switch (type) {
		case -7:// BIT
		case -6: // TINYINT
		case 5: // SMALLINT;
		case 4: {// INTEGER;
			int value = resultSet.getInt(index);
			if (resultSet.wasNull()) {
				return null;
			}
			return value;
		}
		case -5: {// BIGINT;
			long value = resultSet.getLong(index);
			if (resultSet.wasNull()) {
				return null;
			}
			return value;
		}
		case 6: {// FLOAT;
			float value = resultSet.getFloat(index);
			if (resultSet.wasNull()) {
				return null;
			}
			return value;
		}
		case 8: {// DOUBLE;
			double value = resultSet.getDouble(index);
			if (resultSet.wasNull()) {
				return null;
			}
			return value;
		}
		case 3: // DECIMAL;
		case 2: {// NUMERIC;
			BigDecimal value = resultSet.getBigDecimal(index);
			if (resultSet.wasNull()) {
				return null;
			}
			return value;
		}
		case 91: // DATE;
		case 92: // TIME;
		case 93: {// TIMESTAMP;
			Timestamp value = resultSet.getTimestamp(index);
			if (resultSet.wasNull()) {
				return null;
			}
			return new Date(value.getTime());
		}
		case 16: {// BOOLEAN;
			boolean value = resultSet.getBoolean(index);
			if (resultSet.wasNull()) {
				return null;
			}
			return value;
		}
		// case 0: // NULL;
		// case 1: // CHAR;
		// case 12: // VARCHAR;
		// case -1: // LONGVARCHAR
		// case 7: // REAL;
		// case -2: // BINARY;
		// case -3: // VARBINARY;
		// case -4: // LONGVARBINARY;
		// case 1111: // OTHER;
		// case 2000: // JAVA_OBJECT;
		// case 2001: // DISTINCT;
		// case 2002: // STRUCT;
		// case 2003: // ARRAY;
		// case 2004: // BLOB;
		// case 2005: // CLOB;
		// case 2006: // REF;
		// case 70: // DATALINK;
		// case -8: // ROWID;
		// case -15: // NCHAR;
		// case -9: // NVARCHAR;
		// case -16: // LONGNVARCHAR;
		// case 2011: // NCLOB;
		// case 2009: // SQLXML;
		// case 2012: // REF_CURSOR;
		// case 2013: // TIME_WITH_TIMEZONE;
		// case 2014: // TIMESTAMP_WITH_TIMEZONE;
		default: {
			String value = resultSet.getString(index);
			if (resultSet.wasNull()) {
				return null;
			}
			return value;
		}
		}
	}

}
